# -*-coding:utf-8-*-

import json

from pyrestful import mediatypes
from pyrestful.rest import get, post, put, delete
from utils.auth import authenticated
from handlers.base import BaseHandler
from tornado.gen import coroutine, Return
from bson.objectid import ObjectId


class TransfersHandler(BaseHandler):
    def __init__(self, application, request, **kwargs):
        super(TransfersHandler, self).__init__(application, request, **kwargs)

    def check_permissions(self, permissions):
        return True

    @coroutine
    def do_wx_pay_transfers(self, transfer):
        from handlers.weixin.pay import WXPayHandler
        response = yield WXPayHandler.wx_pay_transfers(self, transfer)
        raise Return(response)

    @coroutine
    def do_allinpay_transfers(self, transfer):
        from handlers.allinpay.pay import AllinpayHandler
        response = yield AllinpayHandler.allinpay_transfers(self, transfer)
        raise Return(response)

    '''
    PUT /platform/api/transfers/{tid}/status - 审核转帐/提现申请. 通过设置申请的状态

    status = refused | done

    Request:
    {
        'status': 'refused | done',
        'comment': {} | '',
    }
    '''

    @put(_path='/platform/api/transfers/{tid}/status', _type=[str, dict],
         _consumes=mediatypes.APPLICATION_JSON)
    @authenticated
    @coroutine
    def update_transfer_status(self, tid, request):
        status = request.pop('status')
        if 'done' != status and 'refused' != status:
            raise Exception('illegal status(%s)' % status)
        transfer = yield self.transfers_dao.get_record_by_id(tid)
        transfer_through = transfer.transfer_through
        if 'applying' != transfer.status:
            raise Exception('illegal status(current: %s)' % transfer.status)
        if 'refused' == status:
            data = json.loads(self.request.body)
        else:
            if 'allinpay' == transfer_through:
                data = yield self.do_allinpay_transfers(transfer)
                if '0000' != data['INFO']['RET_CODE']:
                    self.respond_error('external_service_error', data['INFO']['ERR_MSG'])
            elif 'wx' == transfer_through:
                data = yield self.do_wx_pay_transfers(transfer)
                # TODO: CHECK THE RESULT FROM WX
            elif 'manual' == transfer_through:
                data = request
            else:
                raise Exception('unsupported transfer method: %s' % transfer_through)
        result = yield self.transfers_dao.update_transfer_status(self.user_id, tid, status, data, transfer_through)
        self.respond_success(result)

    '''
    POST /platform/api/transfers - 创建转帐/提现申请. 申请未审核前状态为 applying

    Request:
    {
        'amount': 123.45,
        'desc': 'description of this transfer',
        'transfer_through': 'allinpay | wx | manual',
        'specifics': {
            'allinpay': {
                'account_no': 'ACCOUNT_NO',
                'account_name': 'ACCOUNT_NAME',
            },
            'manual': {

            },
        },
    }

    Response:
    {
        'transfer_id': 'TRANSFER_ID',
    }
    '''

    @post(_path='/platform/api/transfers', _types=[dict],
          _consumes=mediatypes.APPLICATION_JSON)
    @authenticated
    @coroutine
    def create_transfer(self, data):
        kwargs = {'aspect': 'commissions'}
        filter_cond = {'uid': self.user_id}
        result = yield self.transfers_dao.find_one(filter_cond, {'_id': 0, 'created_time': 1})
        if result:
            apply_time = result['created_time']
            import time
            if time.strftime('%m') == time.strftime('%m', time.localtime(apply_time)):
                raise Exception('apply once per month')
            kwargs.update(start_time=apply_time)
        kwargs.update(transfer_enable=True)
        pipeline, default = yield self.delegate_pre_get_statistics('orders', **kwargs)
        cursor = self.orders_dao.aggregate(pipeline)
        yield cursor.fetch_next
        result = cursor.next_object()
        if result is None:
            result = default
        data['amount'] = result['commission_as_s'] + result['commission_as_ss'] + result['commission_as_ts']
        if 0 == data['amount']:
            raise Exception('commission is equal to ZERO')
        specifics = data.get('specifics', {})
        specifics.update(amount_detail=result)
        data['specifics'] = specifics
        result = yield self.transfers_dao.create_transfer(self.user.id_str, self.user.specifics_vendor_id, data)
        self.respond_success(result)

    '''
    GET /platform/api/transfers - 获取转帐/提现操作记录列表
    '''

    @get(_path='/platform/api/transfers')
    @authenticated
    @coroutine
    def get_transfer_list(self):
        kwargs = self.query_arguments()
        filter_cond = {'$or': [{'uid': self.user_id}, {'vid': self.user_id}]}
        if 'status' in kwargs:
            filter_cond.update(status=kwargs['status'])
        result = yield self.transfers_dao.get_paging_result(filter_cond, None, 'transfer_id', None, **kwargs)
        self.respond_success(result)

    @get(_path='/platform/api/transfers/{aspect}', _type=[str])
    @authenticated
    @coroutine
    def get_transfer(self, aspect):
        if 'count' == aspect:
            kwargs = self.query_arguments()
            filter_cond = {'$or': [{'uid': self.user_id}, {'vid': self.user_id}]}
            if 'status' in kwargs:
                filter_cond.update(status=kwargs['status'])
            result = yield self.transfers_dao.count(filter_cond)
        elif 'statistics' == aspect:
            result = yield self._get_transfer_statistics()
        else:
            tid = aspect
            filter_cond = {'$or': [{'uid': self.user_id}, {'vid': self.user_id}], '_id': ObjectId(tid)}
            result = yield self.transfers_dao.find_one(filter_cond, {'_id': 0})
        self.respond_success(result)

    @coroutine
    def _get_transfer_statistics(self):
        match = {
            '$or': [
                {'uid': self.user_id},
                {'vid': self.user_id},
            ]
        }
        pipeline = [
            {
                '$match': match,
            },
            {
                '$project': {
                    'commission_as_s': '$specifics.amount_detail.commission_as_s',
                    'commission_as_ss': '$specifics.amount_detail.commission_as_ss',
                    'commission_as_ts': '$specifics.amount_detail.commission_as_ts',
                }
            },
            {
                '$group': {
                    '_id': 0,
                    'commission_as_s': {'$sum': '$commission_as_s'},
                    'commission_as_ss': {'$sum': '$commission_as_ss'},
                    'commission_as_ts': {'$sum': '$commission_as_ts'},
                }
            },
        ]
        default = {
            'commission_as_s': 0,
            'commission_as_ss': 0,
            'commission_as_ts': 0,
        }
        cursor = self.transfers_dao.aggregate(pipeline)
        yield cursor.fetch_next
        result = cursor.next_object()
        if result is None:
            result = default
        raise Return(result)

    '''
    DELETE /api/commissions/transfers/{tid} - 取消转帐/提现申请. 已审核的申请(status = refused | done)不能取消
    '''

    @delete(_path='/platform/api/transfers/{tid}', _types=[str])
    @authenticated
    @coroutine
    def delete_transfer(self, tid):
        result = yield self.transfers_dao.delete_transfer(self.user_id, tid)
        self.respond_success(result)
